home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Science⁄Math / VideoToolbox / VideoToolboxSources / Normal.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-17  |  4.9 KB  |  169 lines  |  [TEXT/KAHL]

  1. /*
  2. Normal.c
  3. statistical functions related to the normal distribution.
  4. Also see: Binomial.c,ChiSquare.c, Exponential.c, Uniform.c
  5. Copyright (c) 1989,1990,1991,1992 Denis G. Pelli
  6. HISTORY:
  7. 1989    dgp wrote it.
  8. 4/8/90    dgp    changed the names of the routines. 
  9.             Made sure that domain error produces NAN.
  10. 6/90    dgp    added NormalSample()
  11. 7/30/91    dgp    now use NAN defined in VideoToolbox.h
  12. 12/28/91 dgp sped up NormalPdf() by calculating the scale factor only once
  13. 12/29/91 dgp extracted code to create new routine UniformSample.c
  14. 1/11/92    dgp    rewrote Normal()'s polynomial evaluation to halve the number of multiplies
  15.             Renamed NormalPDF() to NormalPdf().
  16. 1/19/92    dgp    defined the constants LOG2 and LOGPI in VideoToolbox.h
  17.             Added more domain tests, returning NAN if outside. 
  18.             Added more checks to main().
  19.             Wrote Normal2DPdf(),Normal2D(),InverseNormal2D(),and Normal2DSample().
  20. 2/1/92    dgp    Redefined Normal2DPdf(r) to now, more sensibly, treat r as the random
  21.             variable, rather than the implicit x and y, where r=sqrt(x^2+y^2). 
  22.             Previously, Normal2D(R)=Integrate[2 Pi r Normal2DPdf(r),{r,0,R}]
  23.             now Normal2D(R)=Integrate[Normal2DPdf(r),{r,0,R}]. There is no change
  24.             in Normal2D(). I suspect that Normal2D is in fact the Raleigh distribution,
  25.             and I will rename it if this is in fact the case.
  26. 11/13/92 dgp InverseNormal(0.0) now returns -INF, and InverseNormal(1) returns INF.
  27. 12/15/93 dgp declared some arguments "register".
  28. */
  29. #include "VideoToolbox.h"
  30. #include <assert.h>
  31. #include <math.h>
  32.  
  33. #if 0 /* A test program. */
  34. #include <sane.h>
  35. extended DoubleToExtended(double x);
  36. double ExtendedToDouble(extended x80);
  37. void main()
  38. {
  39.     double x,y,sum,dx,a,b,mean,sd;
  40.     static double z[1000];
  41.     int i;
  42.     extended e,ee;
  43.     
  44.     Require(0);
  45.     srand(clock());
  46.     printf("%4s%15s%15s%20s%15s\n","x","NormalPdf(x)","Normal(x)","InverseNormal","Error");
  47.     for(x=-4.0;x<=4.0;x+=2.0){
  48.         printf("%4.1f%15.8f%15.8f%20.4f%15.4f\n",
  49.         x,NormalPdf(x),Normal(x),InverseNormal(Normal(x)),InverseNormal(Normal(x))-x);
  50.     }
  51.     sum=0.0;
  52.     dx=0.001;
  53.     for(x=-1.;x<0.;x+=dx)sum+=NormalPdf(x);
  54.     sum*=dx;
  55.     sum-=Normal(0.0)-Normal(-1.0);
  56.     printf("Partial integral of NormalPdf error %.5f\n",sum);
  57.     for(i=0;i<1000;i++)z[i]=NormalSample();
  58.     mean=Mean(z,1000,&sd);
  59.     printf("1000 samples mean %.2f sd %.2f\n",mean,sd);
  60.     printf("\n");
  61.  
  62.     printf("%4s%15s%15s%20s%15s\n","x","Normal2DPdf(x)","Normal2D(x)","InverseNormal2D","Error");
  63.     for(x=-1.;x<=5.0;x+=1.0){
  64.         printf("%4.1f%15.8f%15.8f%20.4f%15.4f\n",
  65.         x,Normal2DPdf(x),Normal2D(x),InverseNormal2D(Normal2D(x)),InverseNormal2D(Normal2D(x))-x);
  66.     }
  67.     sum=0.0;
  68.     dx=0.0001;
  69.     for(x=0;x<1.;x+=dx)sum+=Normal2DPdf(x);
  70.     sum*=dx;
  71.     sum-=Normal2D(1.0);
  72.     printf("Partial integral of Normal2DPdf error %.5f\n",sum);
  73.     for(i=0;i<1000;i++)z[i]=Normal2DSample();
  74.     mean=Mean(z,1000,&sd);
  75.     printf("1000 samples rms %.2f\n",sqrt(mean*mean+sd*sd));
  76.     printf("\n");
  77.     for(i=0;i<1000;i++){
  78.         x=NormalSample();
  79.         y=NormalSample();
  80.         z[i]=sqrt((x*x+y*y)/2.);
  81.     }
  82.     mean=Mean(z,1000,&sd);
  83.     printf("1000 (x,y) normal samples with sd 2^-0.5 have rms hypotenuse of %.2f\n",sqrt(mean*mean+sd*sd));
  84.     printf("\n");
  85.  
  86.     a=4.0*atan(1.0);
  87.     if(a!=PI)printf("4*atan(1)-PI %.19f\n",a-PI);
  88.     a=ExtendedToDouble(pi());
  89.     if(a!=PI)printf("Error: pi %.19f, pi-PI %.19f\n",a,a-PI);
  90.     a=log(a);
  91.     if(a!=LOGPI)printf("Error: log(PI) %.19f, error in LOGPI %.19f\n",a,LOGPI-a);
  92.     a=log(2.0);
  93.     if(a!=LOG2)printf("Error: log(2) %.19f, error in LOG2 %.19f\n",a,LOG2-a);
  94. }
  95. #endif
  96.  
  97. double NormalPdf(register double x)
  98. /* Gaussian pdf. Zero mean and unit variance. */
  99. {
  100.     if(IsNan(x))return x;
  101.     return exp(-0.5*(x*x+(LOG2+LOGPI)));
  102. }
  103.  
  104. double Normal(register double x)
  105. /*
  106. Cumulative normal distribution. From Abramowitz and Stegun Eq. (26.2.17).
  107. Error |e|<7.5 10^-8
  108. */
  109. {
  110.     register double P,t;
  111.     
  112.     if(x<0.0) return 1.0-Normal(-x);
  113.     t=1.0/(1.0+0.2316419*x);
  114.     P=(0.319381530+(-0.356563782+(1.781477937+(-1.821255978+1.330274429*t)*t)*t)*t)*t;
  115.     return 1.0-NormalPdf(x)*P;
  116. }
  117.  
  118. double InverseNormal(register double p)
  119. /*
  120. Inverse of Normal(), based on Abramowitz and Stegun Eq. 26.2.23.
  121. Error |e|<4.5 10^-4.
  122. */
  123. {
  124.     register double t,x;
  125.     
  126.     if(IsNan(p))return p;
  127.     if(p<0.0)return NAN;
  128.     if(p==0.0)return -INF;
  129.     if(p>0.5) return -InverseNormal(1.0-p);
  130.     t=sqrt(-2.0*log(p));
  131.     x=t-(2.515517+(0.802853+0.010328*t)*t)/(1.0+(1.432788+(0.189269+0.001308*t)*t)*t);
  132.     return -x;
  133. }
  134.  
  135. double NormalSample(void)
  136. {
  137.     return InverseNormal(UniformSample());
  138. }
  139.  
  140. double Normal2DPdf(double r)
  141. /* Gaussian pdf over two dimensions, integrated over all orientations, 0 to 2π. */
  142. /* The argument is taken to be the distance from the origin, [0,Inf]. */
  143. /* The rms is 1 */
  144. {
  145.     if(IsNan(r))return r;
  146.     if(r<=0.0)return 0.0;
  147.     return 2*r*exp(-r*r);
  148. }
  149.  
  150. double Normal2D(double r)
  151. /* Integral of Normal2DPdf() from zero to r. */
  152. {
  153.     if(IsNan(r))return r;
  154.     if(r<=0.0)return 0.0;
  155.     return 1.0-exp(-r*r);
  156. }
  157.  
  158. double InverseNormal2D(double p)
  159. {
  160.     if(IsNan(p))return p;
  161.     if(p<0.0 || p>1.0)return NAN;
  162.     return sqrt(-log(1.0-p));
  163. }
  164.  
  165. double Normal2DSample(void)
  166. /* rms is 1 */
  167. {
  168.     return InverseNormal2D(UniformSample());
  169. }